home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
X User Tools
/
X User Tools (O'Reilly and Associates)(1994).ISO
/
sources
/
xman
/
misc.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-09-27
|
19KB
|
682 lines
/*
* xman - X window system manual page display program.
*
* $XConsortium: misc.c,v 1.29 91/09/03 18:21:49 dave Exp $
*
* Copyright 1987, 1988 Massachusetts Institute of Technology
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted, provided
* that the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of M.I.T. not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. M.I.T. makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* Author: Chris D. Peterson, MIT Project Athena
* Created: October 27, 1987
*/
#include "globals.h"
#include "vendor.h"
#include <X11/Xos.h> /* sys/types.h and unistd.h included in here */
#include <sys/stat.h>
#include <errno.h>
#include <X11/Xaw/Dialog.h>
#include <X11/Shell.h>
static FILE * Uncompress();
static Boolean UncompressNamed(), UncompressUnformatted();
extern int errno; /* error codes. */
/* Function Name: PopupWarning
* Description: This function pops upa warning message.
* Arguments: string - the specific warning string.
* Returns: none
*/
extern Widget initial_widget, top;
static Widget warnShell, warnDialog;
void
PopdownWarning(w, client, call)
Widget w; XtPointer client, call;
{
XtPopdown((Widget)client);
}
void
PopupWarning(man_globals, string)
ManpageGlobals * man_globals;
char * string;
{
int n;
Arg wargs[3];
Dimension topX, topY;
char buffer[BUFSIZ];
Widget positionto;
Boolean hasPosition;
sprintf( buffer, "Xman Warning: %s", string);
hasPosition = FALSE;
if (man_globals->This_Manpage)
positionto = man_globals->This_Manpage;
else
positionto = top;
if (top)
{
n=0;
XtSetArg(wargs[n], XtNx, &topX); n++;
XtSetArg(wargs[n], XtNy, &topY); n++;
XtGetValues(top, wargs, n);
hasPosition = TRUE;
}
if (man_globals != NULL)
ChangeLabel(man_globals->label, buffer);
if (man_globals->label == NULL) {
n=0;
if (hasPosition)
{
XtSetArg(wargs[n], XtNx, topX); n++;
XtSetArg(wargs[n], XtNy, topY); n++;
}
XtSetArg(wargs[n], XtNtransientFor, top); n++;
warnShell = XtCreatePopupShell("warnShell", transientShellWidgetClass,
initial_widget, wargs, n);
XtSetArg(wargs[0], XtNlabel, buffer);
warnDialog = XtCreateManagedWidget("warnDialog", dialogWidgetClass,
warnShell, wargs, 1);
XawDialogAddButton(warnDialog, "dismiss", PopdownWarning,
(XtPointer)warnShell);
XtRealizeWidget(warnShell);
Popup(warnShell, XtGrabNone);
}
}
/* THIS ROUTINE IS OBSOLETE...
* Function Name: PrintWarning
* Description: This function prints a warning message to stderr.
* Arguments: string - the specific warning string.
* Returns: none
*/
void
PrintWarning(man_globals, string)
ManpageGlobals * man_globals;
char * string;
{
char buffer[BUFSIZ];
sprintf( buffer, "Xman Warning: %s", string);
if (man_globals != NULL)
ChangeLabel(man_globals->label, buffer);
fprintf(stderr, "%s\n", buffer);
}
/* Function Name: PrintError
* Description: This Function prints an error message and exits.
* Arguments: string - the specific message.
* Returns: none. - exits tho.
*/
void
PrintError(string)
char * string;
{
fprintf(stderr,"Xman Error: %s\n",string);
exit(1);
}
/* Function Name: OpenFile
* Description: Assignes a file to the manpage.
* Arguments: man_globals - global structure.
* file - the file pointer.
* Returns: none
*/
void
OpenFile(man_globals, file)
ManpageGlobals * man_globals;
FILE * file;
{
Arg arglist[1];
Cardinal num_args = 0;
XtSetArg(arglist[num_args], XtNfile, file); num_args++;
XtSetValues(man_globals->manpagewidgets.manpage, arglist, num_args);
}
/* Function Name: FindManualFile
* Description: Opens the manual page file given the entry information.
* Arguments: man_globals - the globals info for this manpage.
* section_num - section number of the man page.
* entry_num - entry number of the man page.
* Returns: fp - the file pointer
*
* NOTES:
*
* If there is a uncompressed section it will look there for uncompresed
* manual pages first and then for individually comressed file in the
* uncompressed section.
*
* If there is a compressed directory then it will also look there for
* the manual pages.
*
* If both of these fail then it will attempt to format the manual page.
*/
FILE *
FindManualFile(man_globals, section_num, entry_num)
ManpageGlobals * man_globals;
int section_num, entry_num;
{
FILE * file;
char path[BUFSIZ], page[BUFSIZ], section[BUFSIZ], *temp;
char filename[BUFSIZ];
char * entry = manual[section_num].entries[entry_num];
int len_cat = strlen(CAT);
temp = CreateManpageName(entry);
sprintf(man_globals->manpage_title, "The current manual page is: %s.", temp);
XtFree(temp);
ParseEntry(entry, path, section, page);
/*
* Look for uncompressed files first.
*/
sprintf(filename, "%s/%s%s/%s", path, CAT, section + len_cat, page);
if ( (file = fopen(filename,"r")) != NULL)
return(file);
/*
* Then for compressed files in an uncompressed directory.
*/
sprintf(filename, "%s/%s%s/%s.%s", path, CAT,
section + len_cat, page, COMPRESSION_EXTENSION);
if ( (file = Uncompress(man_globals, filename)) != NULL)
return(file);
/*
* And lastly files in a compressed directory.
*
* The directory is not actually compressed it is just named man#.Z
* and all files in it are compressed without the .Z extension.
* HP does it this way (really :-).
*/
sprintf(filename, "%s/%s%s.%s/%s", path, CAT, section + len_cat,
COMPRESSION_EXTENSION, page);
if ( (file = Uncompress(man_globals, filename)) != NULL)
return(file);
/*
* We did not find any preformatted manual pages, try to format it.
*/
return(Format(man_globals, entry));
}
/* Function Namecompress
* Description: This function will attempt to find a compressed man
* page and uncompress it.
* Arguments: man_globals - the psuedo global info.
* filename - name of file to uncompress.
* Returns:; a pointer to the file or NULL.
*/
static FILE *
Uncompress(man_globals, filename)
ManpageGlobals * man_globals;
char * filename;
{
char tmpfile[BUFSIZ], error_buf[BUFSIZ];
FILE * file;
if ( !UncompressNamed(man_globals, filename, tmpfile) )
return(NULL);
else if ((file = fopen(tmpfile, "r")) == NULL) {
sprintf(error_buf, "Something went wrong in retrieving the %s",
"uncompressed manual page try cleaning up /tmp.");
PopupWarning(man_globals, error_buf);
}
unlink(tmpfile); /* remove name in tree, it will remain
until we close the fd, however. */
return(file);
}
/* Function Name: UncompressNamed
* Description: This function will attempt to find a compressed man
* page and uncompress it.
* Arguments: man_globals - the psuedo global info.
* filename - name of file to uncompress.
* RETURNED output - the file name output (must be an allocated string).
* Returns:; TRUE if the file was found.
*/
static Boolean
UncompressNamed(man_globals, filename, output)
ManpageGlobals * man_globals;
char * filename, * output;
{
char tmp[BUFSIZ], cmdbuf[BUFSIZ], error_buf[BUFSIZ];
struct stat junk;
if (stat(filename, &junk) != 0) { /* Check for existance of the file. */
if (errno != ENOENT) {
sprintf(error_buf, "Error while stating file %s, errno = %d",
filename, errno);
PopupWarning(man_globals, error_buf);
}
return(FALSE);
}
/*
* Using stdin is necessary to fool zcat since we cannot guarentee
* the .Z extension.
*/
strcpy(tmp, MANTEMP); /* get a temp file. */
(void) mktemp(tmp);
strcpy(output, tmp);
sprintf(cmdbuf, UNCOMPRESS_FORMAT, filename, output);
if(system(cmdbuf) == 0) /* execute search. */
return(TRUE);
sprintf(error_buf, "Error while uncompressing, command was: %s", cmdbuf);
PopupWarning(man_globals, error_buf);
return(FALSE);
}
/* Function Name: Format
* Description: This funtion formats the manual pages and interfaces
* with the user.
* Arguments: man_globals - the psuedo globals
* file - the file pointer to use and return
* entry - the current entry struct.
* current_box - The current directory being displayed.
* Returns: none.
*/
/* ARGSUSED */
FILE *
Format(man_globals, entry)
ManpageGlobals * man_globals;
char * entry;
{
FILE * file;
Widget manpage = man_globals->manpagewidgets.manpage;
char cmdbuf[BUFSIZ], tmp[BUFSIZ], filename[BUFSIZ], error_buf[BUFSIZ];
char path[BUFSIZ];
XEvent event;
Position x,y; /* location to pop up the
"would you like to save" widget. */
Popup(XtParent(man_globals->standby), XtGrabExclusive);
while ( !XCheckTypedWindowEvent(XtDisplay(man_globals->standby),
XtWindow(man_globals->standby),
Expose, &event) );
XtDispatchEvent( &event );
XFlush(XtDisplay(man_globals->standby));
if ( !UncompressUnformatted(man_globals, entry, filename) ) {
/* We Really could not find it, this should never happen, yea right. */
sprintf(error_buf, "Could not open manual page, %s", entry);
PopupWarning(man_globals, error_buf);
XtPopdown( XtParent(man_globals->standby) );
return(NULL);
}
strcpy(tmp,MANTEMP); /* Get a temp file. */
(void) mktemp(tmp);
strcpy(man_globals->tmpfile, tmp);
ParseEntry(entry, path, NULL, NULL);
sprintf(cmdbuf,"cd %s ; %s %s %s > %s %s", path, TBL,
filename, FORMAT, man_globals->tmpfile, "2> /dev/null");
if(system(cmdbuf) != 0) { /* execute search. */
sprintf(error_buf,
"Something went wrong trying to run the command: %s", cmdbuf);
PopupWarning(man_globals, error_buf);
file = NULL;
}
else {
if ((file = fopen(man_globals->tmpfile,"r")) == NULL) {
sprintf(error_buf, "Something went wrong in retrieving the %s",
"temp file, try cleaning up /tmp");
PopupWarning(man_globals, error_buf);
}
else {
XtPopdown( XtParent(man_globals->standby) );
if ( (man_globals->save == NULL) ||
(man_globals->manpagewidgets.manpage == NULL) )
unlink(man_globals->tmpfile);
else {
char * ptr, catdir[BUFSIZ];
/*
* If the catdir is writeable then ask the user if he/she wants to
* write the man page to it.
*/
strcpy(catdir, man_globals->save_file);
if ( (ptr = rindex(catdir, '/')) != NULL) {
*ptr = '\0';
if ( access(catdir, W_OK) != 0 )
unlink(man_globals->tmpfile);
else {
x = (Position) Width(man_globals->manpagewidgets.manpage)/2;
y = (Position) Height(man_globals->manpagewidgets.manpage)/2;
XtTranslateCoords(manpage, x, y, &x, &y);
PositionCenter( man_globals->save, (int) x, (int) y, 0, 0, 0, 0);
XtPopup( man_globals->save, XtGrabExclusive);
}
}
else
unlink(man_globals->tmpfile);
}
}
}
if (man_globals->compress) /* If the original was compressed
then this is a tempory file. */
unlink(filename);
return(file);
}
/* Function Name: UncompressUnformatted
* Description: Finds an uncompressed unformatted manual page.
* Arguments: man_globals - the psuedo global structure.
* entry - the manual page entry.
* RETURNED filename - location to put the name of the file.
* Returns: TRUE if the file was found.
*/
static Boolean
UncompressUnformatted(man_globals, entry, filename)
ManpageGlobals * man_globals;
char * entry, * filename;
{
char path[BUFSIZ], page[BUFSIZ], section[BUFSIZ], input[BUFSIZ];
int len_cat = strlen(CAT), len_man = strlen(MAN);
ParseEntry(entry, path, section, page);
/*
* Look for uncompressed file first.
*/
sprintf(filename, "%s/%s%s/%s", path, MAN, section + len_man, page);
if ( access( filename, R_OK ) == 0 ) {
man_globals->compress = FALSE;
sprintf(man_globals->save_file, "%s/%s%s/%s", path,
CAT, section + len_cat, page);
return(TRUE);
}
/*
* Then for compressed files in an uncompressed directory.
*/
sprintf(input, "%s.%s", filename, COMPRESSION_EXTENSION);
if ( UncompressNamed(man_globals, input, filename) ) {
man_globals->compress = TRUE;
sprintf(man_globals->save_file, "%s/%s%s/%s.%s", path,
CAT, section + len_cat, page, COMPRESSION_EXTENSION);
return(TRUE);
}
/*
* And lastly files in a compressed directory.
*/
sprintf(input, "%s/%s%s.%s/%s", path,
MAN, section + len_man, COMPRESSION_EXTENSION, page);
if ( UncompressNamed(man_globals, input, filename) ) {
man_globals->compress = TRUE;
sprintf(man_globals->save_file, "%s/%s%s.%s/%s", path,
CAT, section + len_cat, COMPRESSION_EXTENSION, page);
return(TRUE);
}
return(FALSE);
}
/* Function Name: AddCursor
* Description: This function adds the cursor to the window.
* Arguments: w - the widget to add the cursor to.
* cursor - the cursor to add to this widget.
* Returns: none
*/
void
AddCursor(w,cursor)
Widget w;
Cursor cursor;
{
XColor colors[2];
Arg args[10];
Cardinal num_args = 0;
Colormap c_map;
if (!XtIsRealized(w)) {
PopupWarning(NULL, "Widget is not realized, no cursor added.\n");
return;
}
XtSetArg( args[num_args], XtNcolormap, &c_map); num_args++;
XtGetValues( w, args, num_args);
colors[0].pixel = resources.cursors.fg_color;
colors[1].pixel = resources.cursors.bg_color;
XQueryColors (XtDisplay(w), c_map, colors, 2);
XRecolorCursor(XtDisplay(w), cursor, colors, colors+1);
XDefineCursor(XtDisplay(w),XtWindow(w),cursor);
}
/* Function Name: ChangeLabel
* Description: This function changes the label field of the
* given widget to the string in str.
* Arguments: w - the widget.
* str - the string to change the label to.
* Returns: none
*/
void
ChangeLabel(w,str)
Widget w;
char * str;
{
Arg arglist[3]; /* An argument list. */
if (w == NULL) return;
XtSetArg(arglist[0], XtNlabel, str);
/* shouldn't really have to do this. */
XtSetArg(arglist[1], XtNwidth, 0);
XtSetArg(arglist[2], XtNheight, 0);
XtSetValues(w, arglist, (Cardinal) 1);
}
/*
* In an ideal world this would be part of the XToolkit, and I would not
* have to do it, but such is life sometimes. Perhaps in X11R3.
*/
/* Function Name: PositionCenter
* Description: This fuction positions the given widgets center
* in the following location.
* Arguments: widget - the widget widget to postion
* x,y - The location for the center of the widget
* above - number of pixels above center to locate this widget
* left - number of pixels left of center to locate this widget
* h_space, v_space - how close to get to the edges of the
* parent window.
* Returns: none
* Note: This should only be used with a popup widget that has override
* redirect set.
*/
void
PositionCenter(widget,x,y,above,left,v_space,h_space)
Widget widget;
int x,y,above,left;
int h_space,v_space;
{
Arg wargs[2];
int x_temp,y_temp; /* location of the new window. */
int parent_height,parent_width; /* Height and width of the parent widget or
the root window if it has no parent. */
x_temp = x - left - Width(widget) / 2 + BorderWidth(widget);
y_temp = y - above - Height(widget) / 2 + BorderWidth(widget);
parent_height = HeightOfScreen(XtScreen(widget));
parent_width = WidthOfScreen(XtScreen(widget));
/*
* Check to make sure that all edges are within the viewable part of the
* root window, and if not then force them to be.
*/
if (x_temp < h_space)
x_temp = v_space;
if (y_temp < v_space)
(y_temp = 2);
if ( y_temp + Height(widget) + v_space > parent_height )
y_temp = parent_height - Height(widget) - v_space;
if ( x_temp + Width(widget) + h_space > parent_width )
x_temp = parent_width - Width(widget) - h_space;
XtSetArg(wargs[0], XtNx, x_temp);
XtSetArg(wargs[1], XtNy, y_temp);
XtSetValues(widget, wargs, 2);
}
/* Function Name: ParseEntry(entry, path, sect, page)
* Description: Parses the manual pages entry filenames.
* Arguments: str - the full path name.
* path - the path name. RETURNED
* sect - the section name. RETURNED
* page - the page name. RETURNED
* Returns: none.
*/
void
ParseEntry(entry, path, sect, page)
char *entry, *path, *page, *sect;
{
char *c, temp[BUFSIZ];
strcpy(temp, entry);
c = rindex(temp, '/');
if (c == NULL)
PrintError("index failure in ParseEntry.");
*c++ = '\0';
if (page != NULL)
strcpy(page, c);
c = rindex(temp, '/');
if (c == NULL)
PrintError("index failure in ParseEntry.");
*c++ = '\0';
if (sect != NULL)
strcpy(sect, c);
if (path != NULL)
strcpy(path, temp);
}
/* Function Name: GetGlobals
* Description: Gets the psuedo globals associated with the
* manpage associated with this widget.
* Arguments: w - a widget in the manpage.
* Returns: the psuedo globals.
* Notes: initial_widget is a globals variable.
* manglobals_context is a global variable.
*/
ManpageGlobals *
GetGlobals(w)
Widget w;
{
Widget temp;
caddr_t data;
while ( (temp = XtParent(w)) != initial_widget && (temp != NULL))
w = temp;
if (temp == NULL)
XtAppError(XtWidgetToApplicationContext(w),
"Xman: Could not locate widget in tree, exiting");
if (XFindContext(XtDisplay(w), XtWindow(w),
manglobals_context, &data) != XCSUCCESS)
XtAppError(XtWidgetToApplicationContext(w),
"Xman: Could not find global data, exiting");
return( (ManpageGlobals *) data);
}
/* Function Name: SaveGlobals
* Description: Saves the psuedo globals on the widget passed
* to this function, although GetGlobals assumes that
* the data is associated with the popup child of topBox.
* Arguments: w - the widget to associate the data with.
* globals - data to associate with this widget.
* Returns: none.
* Notes: WIDGET MUST BE REALIZED.
* manglobals_context is a global variable.
*/
void
SaveGlobals(w, globals)
Widget w;
ManpageGlobals * globals;
{
if (XSaveContext(XtDisplay(w), XtWindow(w), manglobals_context,
(caddr_t) globals) != XCSUCCESS)
XtAppError(XtWidgetToApplicationContext(w),
"Xman: Could not save global data, are you out of memory?");
}
/* Function Name: RemoveGlobals
* Description: Removes the psuedo globals from the widget passed
* to this function.
* Arguments: w - the widget to remove the data from.
* Returns: none.
* Notes: WIDGET MUST BE REALIZED.
* manglobals_context is a global variable.
*/
void
RemoveGlobals(w)
Widget w;
{
if (XDeleteContext(XtDisplay(w), XtWindow(w),
manglobals_context) != XCSUCCESS)
XtAppError(XtWidgetToApplicationContext(w),
"Xman: Could not remove global data?");
}